#include "luarun.h"
#include <vfs_fs.h>
lua_State *Lua;
luaL_Rag_All Lreg;
#ifdef LUA_IN_FILE 
#include <unistd.h>
#include <fcntl.h>
char Lstack[LUA_STACK_SIZE];
os_task_t tid;
static int mount_fatfs(void)
{
    if (vfs_mount(OS_FS_PART_NAME, "/", "fat", 0, 0) == 0)
    {
        os_kprintf("FAT filesystem mount successful.\r\n");
    }
    else
    {
        os_kprintf("FAT filesystem mount fail.\r\n");
        os_kprintf("You should mkfs first, then reset board ! cmd: mkfs -t fat %s\r\n", OS_FS_PART_NAME);
    }
		return 0;
} 
OS_CMPOENT_INIT(mount_fatfs, OS_INIT_SUBLEVEL_LOW);
//SH_CMD_EXPORT(mount_fatfs, mount_fatfs, "mount a disk!");

#endif
lua_rd_t lua_Add_Reg(const char *_name)
{
    int iRet = Lreg.m_iRegnum;
    Lreg.m_stReg[iRet].m_iFunnum = 0;
    memset(Lreg.m_stReg[iRet].m_cFunname, 0, 32);
    memset(Lreg.m_stReg[iRet].m_stLuafun, 0, FUN_BUFFER_SIZE);
    strncpy(Lreg.m_stReg[iRet].m_cFunname, _name, strlen(_name));
    Lreg.m_iRegnum++;
    return iRet;
}

int lua_Add_Fun(lua_rd_t _iNo, const char *_name, lua_CFunction _func)
{
    int iNum = Lreg.m_stReg[_iNo].m_iFunnum;
    Lreg.m_stReg[_iNo].m_stLuafun[iNum].name = _name;
    Lreg.m_stReg[_iNo].m_stLuafun[iNum].func = _func;
    Lreg.m_stReg[_iNo].m_iFunnum++;
    return iNum;
}

#ifdef LUA_IN_FILE 
static int Lua_readfile(char * _pFilename, char *_pBuf, int _iBufsize)
{
    int iRet = LUA_OK;
    int fd;
    char cFilename[64];
    memset(cFilename, 0, sizeof(cFilename));
    strncpy(cFilename, SCRIPTS_PATH, sizeof(cFilename));
    strcat(cFilename, _pFilename);
    fd = open(cFilename, O_RDONLY);
	
    if (fd <= 0) 
    {
        iRet = LUA_ERROR;
        goto CLOSE;
    }
    iRet = read(fd, _pBuf, _iBufsize);
    if (LUA_ERROR == iRet)
    {
        goto CLOSE;
    }
CLOSE:
    close(fd);
    return iRet;
}

static void Lua_in_thread(void *pPara)
{
    int iRet = LUA_OK;
    char cLua[LUA_BUFFER_SIZE] = {0};
    memset(cLua, 0, sizeof(cLua));
    os_kprintf("init.lua loading...\r\n");
    iRet = luaL_dostring(Lua, (const char*)pPara);
    if (iRet) {
        os_kprintf("[Lua/init] %s\r\n",lua_tostring(Lua,-1));
        lua_pop(Lua,1);
    }	
    iRet = Lua_readfile("main.lua", cLua, sizeof(cLua));
    if (LUA_ERROR == iRet) 
    {
        os_kprintf("[Lua] Cannot find main.lua!\r\n");
    }
    else
    {
        while (1) 
        {
            iRet = luaL_dostring(Lua, (const char*)cLua);
            if (iRet) {
                os_kprintf("[Lua/main] %s\r\n",lua_tostring(Lua,-1));
                lua_pop(Lua,1);
            }	
        }
    }
}

static int Lua_runtofile(void)
{
    int iRet = LUA_OK;
    char cLua[LUA_BUFFER_SIZE] = {0};
    memset(cLua, 0, sizeof(cLua));
    iRet = Lua_readfile("init.lua", cLua, sizeof(cLua));
    if (LUA_ERROR == iRet) 
    {
        os_kprintf("[Lua] Cannot find init.lua!\r\n");
        goto END;
    }
    else
    {
        iRet = os_task_init(&tid, "lua", Lua_in_thread, cLua, Lstack, LUA_STACK_SIZE, SHELL_TASK_PRIORITY+1);
        if(OS_EOK == iRet)
        {
            os_task_startup(&tid);
        }
    }
END:
    return iRet;
}
#endif

//os_err_t Regnum_init(void)
//{
//    Lreg.m_iRegnum = 0;
//}
//OS_ENV_INIT(Regnum_init, OS_INIT_SUBLEVEL_MIDDLE);

os_err_t Lua_init(void)
{
    int iRet = LUA_OK;
    int i = 0;
    Lua = luaL_newstate(); 	
    luaL_openlibs(Lua);
    for (i = 0; i < Lreg.m_iRegnum; i++)
    {
        luaL_newlibtable(Lua, Lreg.m_stReg[i].m_stLuafun);
        luaL_setfuncs(Lua, Lreg.m_stReg[i].m_stLuafun, 0);
        lua_setglobal(Lua, Lreg.m_stReg[i].m_cFunname);
    }
#ifdef LUA_IN_FILE 
    Lua_runtofile();
#endif
    return iRet;
}
OS_APP_INIT(Lua_init, OS_INIT_SUBLEVEL_MIDDLE);

static int L(int argc, char**argv)
{
    int iRet = LUA_OK;
    int iFlag = 0;
    char cLua[LUA_BUFFER_SIZE] = {0};
    char *pPara = NULL;
    memset(cLua, 0, sizeof(cLua));
    if (argc > 3) 
    {
        os_kprintf("Useage Erroe!\r\n");
        iRet = LUA_ERROR;
        goto END;
    }
    pPara = strstr(argv[1], ".lua");
    if (argv[2] != NULL && argv[2][0] == '&')
    {
        iFlag = 1;
    }
    if (pPara) 
    {
#ifdef LUA_IN_FILE 
        iRet = Lua_readfile(argv[1], cLua, sizeof(cLua));
        if (LUA_ERROR == iRet) 
        {
            os_kprintf("No such file %s\r\n", argv[1]);
            goto END;
        }
#else
        os_kprintf("No support filesystem\r\n");
#endif
    }
    else
    {
        //strncpy(cLua, "print(", strlen("print("));
        strcat(cLua, (const char*)argv[1]);
        //strcat(cLua, ")");
				//printf("%s\n", cLua);
    }
    do {
        iRet = luaL_dostring(Lua, (const char*)cLua);
        if (iRet) {
            os_kprintf("[Lua/REPL] %s\r\n",lua_tostring(Lua,-1));
            lua_pop(Lua,1);
        }	
        if (0 == iFlag) 
        {
            break;
        }
    } while (1);
END:
    return iRet;
}
SH_CMD_EXPORT(L, L, "a Lua Env");
